#include "func.h"

//循环接收，要接多少字节，接完那么多才会返回
int recvn(int new_fd,void* pStart,int len)
{
    int total=0,ret;
    char *p=(char*)pStart;
    while(total<len)
    {
        ret=recv(new_fd,p+total,len-total,0);//ret是接收到的字节数
        ERROR_CHECK(ret,-1,"recv");
        if(0==ret)
        {
            return -1;//对端断开了，返回-1
        }
        total+=ret;
    }
    return 0;
}

//接收文件
int recvFile(int new_fd,char* file_name)
{
    int fd=open(file_name,O_RDWR|O_CREAT|O_APPEND,0666);
    ERROR_CHECK(fd,-1,"open");
    int recvLen;
    //接文件大小
    off_t fileSize;//总长度
    recvn(new_fd,&recvLen,4);
    recvn(new_fd,&fileSize,recvLen);

    struct timeval start,end;
    gettimeofday(&start,NULL);


    off_t downLoadSize=0;
    off_t lastSize=0;
    off_t slice=fileSize/100;//每百分之一
    char buf[1000];

    //接文件内容,接1000的整数倍
    while(fileSize-downLoadSize>=1000)
    {
        recvn(new_fd,buf,1000);//接recvLen长度的数据
        write(fd,buf,1000);
        downLoadSize+=1000;
        if(downLoadSize-lastSize>slice)
        {
            printf("%5.2lf%%\r", 100.0*downLoadSize/fileSize);
            fflush(stdout);
            lastSize = downLoadSize;
        }
    }
    recvn(new_fd,buf,fileSize-downLoadSize); //接最后小于1000个字节的部分
    write(fd,buf,fileSize-downLoadSize);
    
    printf("100.00%%\n");
    gettimeofday(&end,NULL);
    //统计下载总时间
    printf("use time=%ld\n",(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec);
    close(fd);//关闭文件
    return 0;
}

//buf是不同的结构体,发数据
int send_protocal(int new_fd,int control_code,void *pdata,int send_len)
{
    protocol_t t;
    int ret;
    t.size=send_len;//火车头部
    t.control_code=control_code;
    if(pdata)
    {
        memcpy(t.buf,pdata,send_len);//把数据装车
    }
    ret=send(new_fd,&t,8+t.size,0);
    ERROR_CHECK(ret,-1,"send");
    return 0;
}
//buf里可以是任何数据，接数据
int recv_protocal(int new_fd,int *control_code,void *pdata)
{
    int recvLen;
    recvn(new_fd,&recvLen,4);//接火车车厢
    recvn(new_fd,control_code,4);//接控制码
    recvn(new_fd,pdata,recvLen);
    return 0;
}

//发送文件
int transFile(int new_fd,char* file_name)
{
    train_t t;

    //打开文件
    int fd=open(file_name,O_RDONLY);
    ERROR_CHECK(fd,-1,"open");

    //发送文件大小给对端
    struct stat file_buf;
    fstat(fd,&file_buf);
    t.size=sizeof(file_buf.st_size);
    memcpy(t.buf,&file_buf.st_size,sizeof(file_buf.st_size));
    send(new_fd,&t,4+t.size,0);

    //通过sendfile发送文件内容
    long ret=sendfile(new_fd,fd,NULL,file_buf.st_size);
    ERROR_CHECK(ret,-1,"sendfile");
end:
    close(fd);
    return 0;
}